const http = require('http');
const fs = require('fs');
const path = require('path');
const { formidable } = require('formidable');
const crypto = require('crypto'); // 用于验证秘钥

// 日志级别定义
const LOG_LEVELS = {
  DEBUG: 0,
  INFO: 1,
  WARN: 2,
  ERROR: 3
};

// 当前日志级别设置
const CURRENT_LOG_LEVEL = LOG_LEVELS.DEBUG;

// 日志工具函数
const logger = {
  debug: (message, ...args) => {
    if (CURRENT_LOG_LEVEL <= LOG_LEVELS.DEBUG) {
      console.log(`[DEBUG] ${new Date().toISOString()} - ${message}`, ...args);
    }
  },
  info: (message, ...args) => {
    if (CURRENT_LOG_LEVEL <= LOG_LEVELS.INFO) {
      console.log(`[INFO] ${new Date().toISOString()} - ${message}`, ...args);
    }
  },
  warn: (message, ...args) => {
    if (CURRENT_LOG_LEVEL <= LOG_LEVELS.WARN) {
      console.warn(`[WARN] ${new Date().toISOString()} - ${message}`, ...args);
    }
  },
  error: (message, ...args) => {
    if (CURRENT_LOG_LEVEL <= LOG_LEVELS.ERROR) {
      console.error(`[ERROR] ${new Date().toISOString()} - ${message}`, ...args);
    }
  }
};

// 确保上传目录存在
const uploadDir = path.join(__dirname, 'uploads');
logger.debug('上传目录路径:', uploadDir);
if (!fs.existsSync(uploadDir)) {
  logger.info('上传目录不存在，正在创建...');
  try {
    fs.mkdirSync(uploadDir, { recursive: true });
    logger.info('上传目录创建成功');
  } catch (err) {
    logger.error('创建上传目录失败:', err);
    throw err; // 如果无法创建上传目录，则抛出错误终止程序
  }
} else {
  logger.info('上传目录已存在');
}

// 配置预先约定好的秘钥
const API_SECRET_KEY = 'your-secret-key-12345'; // 这个秘钥应该保密并且在生产环境中使用更复杂的值

// 验证请求的函数
const verifyApiKey = (req) => {
  const apiKey = req.headers['x-api-key'];
  logger.debug('验证API密钥, 请求头:', { 'x-api-key': apiKey });
  
  // 如果没有提供API密钥，返回false
  if (!apiKey) {
    logger.warn('API密钥验证失败: 未提供密钥');
    return false;
  }
  
  // 简单的密钥匹配验证
  const isValid = apiKey === API_SECRET_KEY;
  if (isValid) {
    logger.info('API密钥验证成功');
  } else {
    logger.warn('API密钥验证失败: 密钥不匹配');
  }
  return isValid;
};

// 验证HMAC签名的函数
const verifyHmacSignature = (req) => {
  const signature = req.headers['x-signature'];
  const timestamp = req.headers['x-timestamp'];
  
  logger.debug('验证HMAC签名, 请求头:', { 
    'x-signature': signature, 
    'x-timestamp': timestamp 
  });
  
  // 如果没有提供签名或时间戳，返回false
  if (!signature || !timestamp) {
    logger.warn('HMAC签名验证失败: 缺少签名或时间戳');
    return false;
  }
  
  // 检查时间戳是否在有效期内（例如5分钟）
  const currentTime = Math.floor(Date.now() / 1000);
  const timestampValue = parseInt(timestamp, 10);
  const timeDiff = currentTime - timestampValue;
  
  logger.debug('时间戳验证:', { 
    当前时间: currentTime, 
    请求时间戳: timestampValue, 
    时间差: timeDiff, 
    有效期: 300 
  });
  
  if (isNaN(timestampValue)) {
    logger.warn('HMAC签名验证失败: 时间戳格式无效');
    return false;
  }
  
  if (timeDiff > 300) { // 5分钟过期
    logger.warn(`HMAC签名验证失败: 时间戳已过期 (${timeDiff}秒 > 300秒)`);
    return false;
  }
  
  // 计算预期的签名
  // 签名格式: HMAC-SHA256(timestamp + API_SECRET_KEY)
  try {
    const expectedSignature = crypto
      .createHmac('sha256', API_SECRET_KEY)
      .update(timestamp)
      .digest('hex');
    
    logger.debug('签名比对:', { 
      接收到的签名: signature, 
      计算的签名: expectedSignature 
    });
    
    // 验证签名是否匹配
    const isValid = crypto.timingSafeEqual(
      Buffer.from(signature, 'hex'), 
      Buffer.from(expectedSignature, 'hex')
    );
    
    if (isValid) {
      logger.info('HMAC签名验证成功');
    } else {
      logger.warn('HMAC签名验证失败: 签名不匹配');
    }
    
    return isValid;
  } catch (err) {
    logger.error('HMAC签名验证过程中发生错误:', err);
    return false;
  }
};

// 创建一个简单的HTML表单用于文件上传
const createUploadForm = () => {
  return `
    <!DOCTYPE html>
    <html>
    <head>
      <title>文件上传服务器</title>
      <meta charset="utf-8">
      <style>
        body {
          font-family: Arial, sans-serif;
          max-width: 800px;
          margin: 0 auto;
          padding: 20px;
        }
        h1 {
          color: #333;
        }
        form {
          border: 1px solid #ddd;
          padding: 20px;
          border-radius: 5px;
          background-color: #f9f9f9;
        }
        input[type="file"] {
          margin: 10px 0;
        }
        input[type="submit"] {
          background-color: #4CAF50;
          color: white;
          padding: 10px 15px;
          border: none;
          border-radius: 4px;
          cursor: pointer;
        }
        input[type="submit"]:hover {
          background-color: #45a049;
        }
        .success {
          color: green;
          margin-top: 10px;
        }
      </style>
    </head>
    <body>
      <h1>文件上传服务器</h1>
      <form action="/upload" method="post" enctype="multipart/form-data">
        <div>
          <label for="file">选择文件：</label>
          <input type="file" name="file" id="file" multiple>
        </div>
        <div>
          <input type="submit" value="上传">
        </div>
      </form>
    </body>
    </html>
  `;
};

// 创建HTTP服务器
const server = http.createServer((req, res) => {
  const clientIP = req.socket.remoteAddress;
  const requestMethod = req.method;
  const requestUrl = req.url;
  
  logger.info(`收到请求: ${requestMethod} ${requestUrl} 来自 ${clientIP}`);
  logger.debug('请求头:', req.headers);
  
  // 处理首页请求，显示上传表单
  if (req.url === '/' && req.method.toLowerCase() === 'get') {
    logger.debug('处理首页请求');
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end(createUploadForm());
    logger.debug('首页请求处理完成');
    return;
  }

  // 处理文件上传请求 - HTML表单响应
  if (req.url === '/upload' && req.method.toLowerCase() === 'post') {
    logger.info('处理文件上传请求');
    
    // 检查请求头中是否包含Accept: application/json，决定返回JSON还是HTML
    const acceptJson = req.headers.accept && req.headers.accept.includes('application/json');
    logger.debug('请求类型:', acceptJson ? 'API请求(JSON)' : 'HTML表单请求');
    
    // 验证API请求
    // 如果是API请求（JSON响应），则需要验证秘钥
    if (acceptJson) {
      logger.info('API请求，开始验证');
      
      // 验证API密钥或HMAC签名
      const isValidApiKey = verifyApiKey(req);
      const isValidSignature = verifyHmacSignature(req);
      
      logger.debug('验证结果:', { API密钥验证: isValidApiKey, HMAC签名验证: isValidSignature });
      
      // 如果两种验证方式都失败，则返回401未授权错误
      if (!isValidApiKey && !isValidSignature) {
        logger.warn('验证失败，返回401未授权错误');
        res.writeHead(401, { 'Content-Type': 'application/json; charset=utf-8' });
        res.end(JSON.stringify({
          success: false,
          error: '未授权的请求，缺少有效的API密钥或签名'
        }));
        return;
      }
      
      logger.info('API请求验证通过');
    }
    
    // 配置formidable
    logger.debug('配置formidable');
    const maxFileSize = 200 * 1024 * 1024; // 200MB
    const form = formidable({
      multiples: true,           // 支持多文件上传
      uploadDir: uploadDir,     // 设置上传目录
      keepExtensions: true,     // 保留文件扩展名
      maxFileSize: maxFileSize, // 设置最大文件大小（200MB）
    });
    
    logger.debug('formidable配置:', { 
      multiples: true, 
      uploadDir, 
      keepExtensions: true, 
      maxFileSize: `${maxFileSize / (1024 * 1024)}MB` 
    });

    logger.info('开始解析上传的表单数据');
    // 解析上传的表单数据
    form.parse(req, (err, fields, files) => {
      if (err) {
        logger.error('解析表单出错:', err);
        
        if (acceptJson) {
          // 返回JSON错误响应
          logger.debug('返回JSON错误响应');
          res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
          res.end(JSON.stringify({
            success: false,
            error: err.message
          }));
        } else {
          // 返回HTML错误响应
          logger.debug('返回HTML错误响应');
          res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
          res.end('文件上传失败: ' + err.message);
        }
        return;
      }
      
      logger.info('表单数据解析成功');
      logger.debug('表单字段:', fields);

      // 处理上传的文件
      let fileInfo = '';
      let uploadedFiles = [];
      
      logger.debug('处理上传的文件');
      
      if (files.file) {
        const fileArray = Array.isArray(files.file) ? files.file : [files.file];
        logger.debug(`检测到文件: ${fileArray.length}个`);
        
        uploadedFiles = fileArray.map(file => {
          logger.debug(`文件信息:`, {
            原始名称: file.originalFilename,
            大小: `${(file.size / 1024).toFixed(2)}KB`,
            类型: file.mimetype,
            临时路径: file.filepath
          });
          
          return {
            originalName: file.originalFilename,
            newName: file.newFilename,
            size: file.size,
            type: file.mimetype,
            path: path.relative(__dirname, file.filepath)
          };
        });
        
        fileInfo = fileArray.map(file => {
          return `文件 "${file.originalFilename}" 上传成功，保存为 ${file.newFilename}`;
        }).join('<br>');
        
        logger.info(`成功处理${fileArray.length}个文件`);
      } else {
        logger.warn('没有检测到上传的文件');
      }

      if (acceptJson) {
        // 返回JSON成功响应
        logger.info('生成JSON成功响应');
        logger.debug('响应数据:', { success: true, files: uploadedFiles, fields: fields });
        
        res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
        res.end(JSON.stringify({
          success: true,
          files: uploadedFiles,
          fields: fields
        }));
        
        logger.info('JSON响应已发送');
      } else {
        // 返回HTML成功响应
        logger.info('生成HTML成功响应');
        logger.debug('成功消息:', fileInfo);
        
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
        res.end(`
          ${createUploadForm()}
          <div class="success">${fileInfo}</div>
        `);
        
        logger.info('HTML响应已发送');
      }
    });
    return;
  }

  // 处理API文档请求
  if (req.url === '/api-docs' && req.method.toLowerCase() === 'get') {
    logger.info('处理API文档请求');
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end(`
      <!DOCTYPE html>
      <html>
      <head>
        <title>文件上传服务器 API 文档</title>
        <meta charset="utf-8">
        <style>
          body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
          }
          h1, h2, h3 {
            color: #333;
          }
          .endpoint {
            border: 1px solid #ddd;
            padding: 20px;
            border-radius: 5px;
            background-color: #f9f9f9;
            margin-bottom: 20px;
          }
          .method {
            display: inline-block;
            padding: 5px 10px;
            border-radius: 3px;
            background-color: #4CAF50;
            color: white;
            font-weight: bold;
          }
          pre {
            background-color: #f1f1f1;
            padding: 10px;
            border-radius: 3px;
            overflow-x: auto;
          }
          code {
            font-family: monospace;
          }
          table {
            width: 100%;
            border-collapse: collapse;
          }
          th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
          }
          th {
            background-color: #f2f2f2;
          }
        </style>
      </head>
      <body>
        <h1>文件上传服务器 API 文档</h1>
        
        <div class="endpoint">
          <h2><span class="method">POST</span> /upload</h2>
          <p>上传一个或多个文件到服务器</p>
          
          <h3>请求</h3>
          <p>Content-Type: multipart/form-data</p>
          
          <h3>认证</h3>
          <p>API请求需要通过以下两种方式之一进行认证：</p>
          
          <h4>方式1：API密钥</h4>
          <p>在请求头中添加 <code>X-API-Key</code> 字段：</p>
          <pre><code>X-API-Key: your-secret-key-12345</code></pre>
          
          <h4>方式2：HMAC签名</h4>
          <p>在请求头中添加以下字段：</p>
          <pre><code>X-Timestamp: 当前的UNIX时间戳（秒）
X-Signature: HMAC-SHA256签名</code></pre>
          
          <p>签名生成方法：</p>
          <pre><code>// 使用密钥对时间戳进行HMAC-SHA256签名
signature = HMAC-SHA256(timestamp, secretKey)</code></pre>
          
          <h3>参数</h3>
          <table>
            <tr>
              <th>名称</th>
              <th>类型</th>
              <th>描述</th>
            </tr>
            <tr>
              <td>file</td>
              <td>File</td>
              <td>要上传的文件（可以是多个文件）</td>
            </tr>
            <tr>
              <td>其他字段</td>
              <td>String</td>
              <td>可以添加任意其他表单字段</td>
            </tr>
          </table>
          
          <h3>响应</h3>
          <p>当请求头包含 <code>Accept: application/json</code> 时，返回JSON格式响应：</p>
          
          <h4>成功响应 (200 OK)</h4>
          <pre><code>{
  "success": true,
  "files": [
    {
      "originalName": "example.jpg",
      "newName": "upload_1234567890123.jpg",
      "size": 12345,
      "type": "image/jpeg",
      "path": "uploads/upload_1234567890123.jpg"
    }
  ],
  "fields": {
    // 其他表单字段
  }
}</code></pre>

          <h4>错误响应 (500 Internal Server Error)</h4>
          <pre><code>{
  "success": false,
  "error": "错误信息"
}</code></pre>
          
          <h3>示例</h3>
          <h4>使用curl</h4>
          <pre><code># 使用API密钥方式
curl -X POST \
  -H "Accept: application/json" \
  -H "X-API-Key: your-secret-key-12345" \
  -F "file=@/path/to/file.jpg" \
  http://localhost:${PORT}/upload

# 使用HMAC签名方式
TIMESTAMP=$(date +%s)
SIGNATURE=$(echo -n "$TIMESTAMP" | openssl dgst -sha256 -hmac "your-secret-key-12345" -hex | sed 's/^.* //')

curl -X POST \
  -H "Accept: application/json" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $SIGNATURE" \
  -F "file=@/path/to/file.jpg" \
  http://localhost:${PORT}/upload</code></pre>
          
          <h4>使用JavaScript Fetch API</h4>
          <pre><code>// 使用API密钥方式
const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('http://localhost:${PORT}/upload', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'X-API-Key': 'your-secret-key-12345'
  },
  body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));

// 使用HMAC签名方式
const generateSignature = async (timestamp, secretKey) => {
  // 注意：在浏览器环境中使用Web Crypto API
  const encoder = new TextEncoder();
  const key = await crypto.subtle.importKey(
    'raw', 
    encoder.encode(secretKey),
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign']
  );
  
  const signature = await crypto.subtle.sign(
    'HMAC',
    key,
    encoder.encode(timestamp)
  );
  
  // 转换为十六进制字符串
  return Array.from(new Uint8Array(signature))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
};

const uploadWithSignature = async () => {
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);
  
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const signature = await generateSignature(timestamp, 'your-secret-key-12345');
  
  fetch('http://localhost:${PORT}/upload', {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'X-Timestamp': timestamp,
      'X-Signature': signature
    },
    body: formData
  })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
};

// 调用上传函数
uploadWithSignature();</code></pre>
        </div>
      </body>
      </html>
    `);
    logger.info('API文档响应已发送');
    return;
  }
  
  // 处理其他请求
  res.writeHead(404, { 'Content-Type': 'text/plain' });
  res.end('404 Not Found');
});

// 启动服务器
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  logger.info(`服务器启动成功，监听端口 ${PORT}`);
  logger.info(`服务器地址: http://localhost:${PORT}`);
  logger.info(`上传目录: ${uploadDir}`);
  logger.info('API文档: http://localhost:' + PORT + '/api-docs');
  logger.debug('服务器配置:', {
    端口: PORT,
    上传目录: uploadDir,
    最大文件大小: '200MB',
    API密钥: API_SECRET_KEY ? '已配置' : '未配置',
    日志级别: CURRENT_LOG_LEVEL
  });
});

// 添加错误处理
server.on('error', (err) => {
  logger.error('服务器错误:', err);
  if (err.code === 'EADDRINUSE') {
    logger.error(`端口 ${PORT} 已被占用，请尝试使用其他端口`);
  }
});

process.on('uncaughtException', (err) => {
  logger.error('未捕获的异常:', err);
});

process.on('unhandledRejection', (reason, promise) => {
  logger.error('未处理的Promise拒绝:', reason);
});